19.1 创建
同步和异步的区别,在于是否有缓冲槽。
chan.go
type hchan struct { dataqsiz uint // 缓冲槽大小(可存储数据项数量) buf unsafe.Pointer // 缓冲槽指针 elemsize uint16 // 数据项大小 elemtype *_type // 数据项类型 }
chan.go
func makechan(t *chantype, size int64) *hchan { elem := t.elem // 数据项不能超过 64KB(这时候用指针更合适一些) if elem.size >= 1<<16 { throw(“makechan: invalid channel element type”) } // 缓冲槽大小检查 if size < 0 || int64(uintptr(size)) != size || (elem.size > 0 && uintptr(size) > (_MaxMem-hchanSize)/uintptr(elem.size)) { panic(“makechan: size out of range”) } var c *hchan // 受垃圾回收器限制,指针类型缓冲槽须单独分配内存 if elem.kind&kindNoPointers != 0 || size == 0 { // 因为缓冲槽大小固定,所以可一次性分配内存 c = (*hchan)(mallocgc(hchanSize+uintptr(size)*uintptr(elem.size), nil, flagNoScan)) if size > 0 && elem.size != 0 { // 调整缓冲槽起始指针 c.buf = add(unsafe.Pointer(c), hchanSize) } else { c.buf = unsafe.Pointer(c) } } else { c = new(hchan) c.buf = newarray(elem, uintptr(size)) } // 设置属性 c.elemsize = uint16(elem.size) c.elemtype = elem c.dataqsiz = uint(size) return c }